import React, { Component } from 'react'

import FilterTitle from '../FilterTitle'
import FilterPicker from '../FilterPicker'
import FilterMore from '../FilterMore'

import styles from './index.module.css'

//导入封装好的axios
import { instance } from '../../../../utils/api'

//导入 Spring 
import { Spring } from 'react-spring/renderprops'

//判断高亮的条件
const titleSelectedStatus = {
  area: false,
  mode: false,
  price: false,
  more: false
}

// 默认选中的状态
const selectedValues = {
  area: ["area", null],
  mode: ["null"],
  price: ["null"],
  more: []
};


/* 

思路分析
- 点击前三个标题展示该组件，点击取消的时候隐藏
- 使用PickerView组件来实现页面效果
- 获取到PickerView组件中，选中的筛选条件值
- 点击确定按钮，隐藏该组件，将获取到的筛选条件值传递给父组件
- 展示或隐藏对话框的状态：由父组件提供，通过props传递给子组件
- 筛选条件数据：由父组件提供（因为所有筛选条件是通过一个接口来获取的），通过props传递给子组件

*/





export default class Filter extends Component {
  state = {
    titleSelectedStatus,
    //定义openType，实现FilterPicker显示隐藏
    openType: null,
    //将数据保存为状态：filtersData
    filtersData: {},
    //筛选默认选中的状态值
    selectedValues
  }




  //子元素传递过来的值，修改openType的值
  beClicking = (msg) => {

    //给 body 添加样式
    this.htmlBody.className = 'body-fixed'

    /* 
    - 点击标题时，遍历标题高亮数据
    - 如果是当前标题，直接设置为高亮
    - 分别判断每个标题对应的筛选条件有没有选中值（判断每个筛选条件的选中值与默认值是否相同，相同表示没有选中值，不同，表示选中了值）
    - selectedVal 表示当前type的选中值
    - 如果type为area，此时，selectedVal.length !== 2 || selectedVal[0] !== 'area'，就表示已经有选中值
    - 如果 type 为 mode，此时，selectedVal[0] !== 'null'，就表示已经有选中值
    - 如果 type 为 price，此时，selectedVal[0] !== 'null'，就表示有选中值
    - 如果有，就让该标题保持高亮
    - 如果没有，就让该标题取消高亮
    */

    //在标题点击事件 onTitleClick事件里面，获取到两个状态：标题选中状态对象和筛选条件的选中值对象
    const { titleSelectedStatus, selectedValues } = this.state

    //根据当前标题选中状态对象，获取到一个新的标题选中状态对象（newTitleSelectedStatus）
    //react的一个原则，就是不要去修改当前的对象，而是去创建新的对象
    const newTitleSelectedStatus = {
      ...titleSelectedStatus
    }
    //使用Object.keys()，遍历标题选中状态对象
    Object.keys(titleSelectedStatus).forEach(key => {
      //先判断是否为当前标题，如果是，直接让该标题选中状态为true（高亮
      if (key === msg) {
        newTitleSelectedStatus[msg] = true
        return
      }
      //否则，分别判断每个标题的选中值是否与默认值相同
      //如果不同，则设置该标题的选中状态为true
      //如果相同，则设置该标题的选中状态为false
      //其他标题
      //该值是用来判断，不同的分支是不是被选中还是默认值，如果是默认值，就不高亮，如果不是默认值就高亮
      //注意：key表示我们当前遍历的那个值，msg表示我们当前点的那个值
      let selectedVal = selectedValues[key]
      if (key === 'area' && (selectedVal.length !== 2 || selectedVal[0] !== 'area')) {
        newTitleSelectedStatus[key] = true
      } else if (key === 'mode' && selectedVal[0] !== 'null') {
        newTitleSelectedStatus[key] = true
      } else if (key === 'price' && selectedVal[0] !== 'null') {
        newTitleSelectedStatus[key] = true
      } else if (key === 'more' && selectedVal.length !== 0) {
        //更多的选择
        newTitleSelectedStatus[key] = true
      } else {
        newTitleSelectedStatus[key] = false
      }
    })
    //在 onTitleClick方法中，修改状态 openType为当前 type，展示对话框
    this.setState(() => {
      return {
        titleSelectedStatus: newTitleSelectedStatus,
        openType: msg
      }
    })
  }


  //在Filter组件中，提供onCancel方法（作为取消按钮和遮罩层的事件）
  onCancel = type => {

    this.htmlBody.className = ''

    const { titleSelectedStatus, selectedValues } = this.state;
    let newTitleSelectedStatus = { ...titleSelectedStatus };
    let selectedVal = selectedValues[type];

    console.log(selectedVal);

    //点击取消之后，进行逻辑判断
    if (type === 'area' && (selectedVal.length !== 2 || selectedVal[0] !== 'area')) {
      newTitleSelectedStatus[type] = true
    } else if (type === 'mode' && selectedVal[0] !== 'null') {
      newTitleSelectedStatus[type] = true
    } else if (type === 'price' && selectedVal[0] !== 'null') {
      newTitleSelectedStatus[type] = true
    } else if (type === 'more' && selectedVal.length !== 0) {
      //更多的选择
      newTitleSelectedStatus[type] = true
    } else {
      newTitleSelectedStatus[type] = false
    }

    //在关闭对话框时（onCancel），根据type和当前type的选中值，判断当前菜单是否高亮
    console.log(type);

    this.setState(() => {
      return {
        openType: null,
        titleSelectedStatus: newTitleSelectedStatus,
      }
    })
  }


  //在Filter组件中，提供onSave方法，作为确定按钮的事件处理
  //在点击确定按钮后，在父组件中更新当前type对应的selectedValues状态值
  onSave = (value, type) => {

    this.htmlBody.className = ''


    const { titleSelectedStatus } = this.state;
    let newTitleSelectedStatus = { ...titleSelectedStatus };
    let selectedVal = value;

    //点击确认之后，进行逻辑判断
    if (type === 'area' && (selectedVal.length !== 2 || selectedVal[0] !== 'area')) {
      newTitleSelectedStatus[type] = true
    } else if (type === 'mode' && selectedVal[0] !== 'null') {
      newTitleSelectedStatus[type] = true
    } else if (type === 'price' && selectedVal[0] !== 'null') {
      newTitleSelectedStatus[type] = true
    } else if (type === 'more' && selectedVal.length !== 0) {
      //更多的选择
      newTitleSelectedStatus[type] = true
    } else {
      newTitleSelectedStatus[type] = false
    }

    //组拼数据格式
    const newSelectedValues = {
      ...this.state.selectedValues,
      [type]: value
    }

    //结构数据格式里面的数据
    const { area, mode, price, more } = newSelectedValues
    //筛选条件数据
    let filters;
    //区域
    const areaKey = area[0];
    let areaValue = ''
    if (area.length === 3) {
      areaValue = area[2] !== "null" ? area[2] : area[1]
    }
    filters[areaKey] = areaValue
    // 方式和租金
    filters.mode = mode[0]
    filters.price = price[0]

    // 更多筛选条件 more
    filters.more = more.join(',')

    //console.log(filters)
    //使用条件筛选查询数据时，页面没有回到顶部（需要解决：每次重新回到页面顶部）
    //注意window的方法是父组件的方法，这个 onSave 仅仅是对应的这个组件，而我们希望父组件的页面滚动，这里调用了父组件的方法，所以我们回到了父组件里面，来调用window的方法！
    //调用父组件的方法，使得父组件获取筛选数据
    this.props.onFilters(filters)




    this.setState(() => {
      return {
        openType: '',
        titleSelectedStatus: newTitleSelectedStatus,
        selectedValues: newSelectedValues
      }
    })
  }


  //发送请求，获取所有筛选条件数据
  async getFilterData() {
    //获取对应城市的ID
    const { value } = JSON.parse(localStorage.getItem('now_city'))
    const { data: res } = await instance.get('/houses/condition', {
      params: {
        id: value
      }
    })
    if (res.status !== 200) {
      return console.error(res.description)
    }
    this.setState(() => {
      return {
        filtersData: res.body
      }
    })
  }


  //封装方法 renderFilterPicker 来渲染FilterPicker组件
  renderFilterPicker() {
    const {
      openType,
      filtersData: { area, subway, rentType, price },
      selectedValues
    } = this.state

    //data是筛选选择器中所展示的数据
    let data = []

    //通过openType获取到当前类型的选中值（defaultValue），通过props传递给FilterPicker组件
    let defaultValue = selectedValues[openType]

    // pickerView显示的列数
    let cols = 3

    if (openType !== 'area' && openType !== 'mode' && openType !== 'price') {
      return null
    }

    //拼接数据
    switch (openType) {
      case 'area':
        data = [area, subway]
        break;
      case 'mode':
        data = rentType
        cols = 1
        break;
      case 'price':
        data = price
        cols = 1
        break;

      default:
        break;
    }

    return (< FilterPicker
      key={openType}
      onCancel={this.onCancel}
      onSave={this.onSave}
      data={data}
      cols={cols}
      type={openType}
      defaultValue={defaultValue}
    />)
  }


  //封装renderFilterMore方法，渲染FilterMore组件
  renderFilterMore() {
    //从filtersData中，获取数据（roomType，oriented，floor，characteristic），通过props传递给FilterMore组件
    const { openType, filtersData: { roomType, oriented, floor, characteristic }, selectedValues: { more } } = this.state
    //把数据放在一个对象里面，方便传递
    const data = {
      roomType,
      oriented,
      floor,
      characteristic
    }
    if (openType !== 'more') {
      return null
    }
    //传递给子组件
    return <FilterMore
      data={data}
      type={openType}
      onSave={this.onSave}
      more={more}
      onCancel={this.onCancel} />
  }

  //渲染遮罩层
  renderMask() {
    const { openType } = this.state
    const isHide = openType === 'more' || openType === null
    console.log(isHide);
    console.log(openType);

    return (
      <Spring
        from={{ opacity: 0 }}
        to={{ opacity: isHide ? 0 : 1 }}
      >
        {props => {
          //说明遮罩层已经完成动画效果，隐藏了
          if (props.opacity === 0) {
            return null
          }
          return <div style={props} className={styles.mask} onClick={() => this.onCancel(openType)} />
        }}
      </Spring>)

  }

  componentDidMount() {
    this.getFilterData()
    //获取到 body
    this.htmlBody = document.body
  }


  //使用 react-spring 动画库
  //  安装： yarn add react-spring
  //  打开Spring组件文档
  //  导入Spring文档，使用Spring组件包裹要实现动画效果的遮罩层div
  //  通过render-props模式，讲参数props设置为遮罩层div的style
  //  给Spring组件添加from属性，指定：组件第一次渲染时的动画状态
  //  给Spring组件添加to属性，指定：组件要更新的新动画状态
  //  props就是透明度有0~1中变化的值




  render() {
    return (
      < div className={styles.root} >
        {/* 在render方法中判断 openType的值为 area/mode/price 时，就显示 FilterPicker组件，以及遮罩层 */}

        {/* 前三个菜单的遮罩层 */}
        {/* 在Filter组件中，提供onCancel方法（作为取消按钮和遮罩层的事件） */}
        {this.renderMask()}


        <div className={styles.content}>
          {/* 标题栏 */}
          <FilterTitle
            titleSelectedStatus={this.state.titleSelectedStatus}
            beClicking={this.beClicking}
          />

          {/* 前三个菜单对应的内容： */}
          {/* 在Filter组件中，提供onCancel方法（作为取消按钮和遮罩层的事件） */}
          {/* 在Filter组件中，提供onSave方法，作为确定按钮的事件处理 */}
          {this.renderFilterPicker()}


          {/* 最后一个菜单对应的内容： */}
          {this.renderFilterMore()}
          {/* <FilterMore /> */}
        </div>
      </div >
    )
  }
}
